home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cmln0585.arc / BMLP.DOC < prev    next >
Text File  |  1986-02-27  |  58KB  |  1,781 lines

  1.  
  2.  
  3.                 BMLP MACRO LANGUAGE PREPROCESSOR
  4.  
  5.  
  6.  
  7.     INTRODUCTION 
  8.  
  9.          BMLP and BSLP  are  preprocessor  tools for  Microsoft BASIC.
  10.          
  11.          BMLP is a macro language preprocessor. It allows you to write 
  12.          your programs using macros which you define in the program or 
  13.          within macro library text files.  
  14.          
  15.          BSLP  takes  a  source  file  containing  special  structured 
  16.          statements and translates it into a program containing  BASIC 
  17.          statements.  
  18.          
  19.          Using these tools will help you write  more  concise,  better
  20.          structured BASIC programs,  by allowing you to take advantage
  21.          of these features:
  22.          
  23.          - program  with macros  using parameters and subroutines that
  24.            are  maintained in  libraries where they can be accessed by 
  25.            all your programs.  
  26.          
  27.          - write free-form, indented statements without  line  numbers.  
  28.  
  29.          - include statements from many separate files  and  libraries 
  30.            into  a  single  BASIC  program.  (This lets  you write and 
  31.            maintain your programs in small modules.)  
  32.  
  33.          - organize your subroutines into procedures,  each  with  its 
  34.            own descriptive alpha-numeric name.  
  35.  
  36.          - structure  your programming  with multi-line  conditionals,
  37.            loop  and  case   constructs  similar  to  those  found  in 
  38.            programming languages like C and Pascal.  
  39.  
  40.          When using these preprocessors,  please  bear  in  mind  that 
  41.          these versions are written in BASIC and are provided for your 
  42.          use and you are free to modify them in any manner you see fit.  
  43.          
  44.          If you find these tools useful, we have a package called  PPE 
  45.          (Professional Programming Environment) that  includes a super 
  46.          preprocessor   (SLPC)  which  is  written  in  C  for  faster 
  47.          processing  (300-400  lines/min).  It  does  everything  that 
  48.          these  do PLUS a lot more,  like providing a define statement 
  49.          for text substitution and built-in random file handling macro 
  50.          statements.  It comes with a large library of  macros  and  a 
  51.          library manager program.  
  52.          
  53.          If  you have suggestions,  questions,  comments or would like 
  54.          more information about the PPE package, 
  55.          please contact us at:è
  56.                  Bendorf Associates
  57.                  P.O. Box 5910
  58.                  6006 S. Main
  59.                  Roswell, NM 88201
  60.                  (505) 347-5701
  61.         
  62.          The following is a list  and  brief  abstract of the files on
  63.          this disk:           
  64.  
  65.          Files for BSLP: Basic Structured Language Preprocessor 
  66.  
  67.            BSLP.P . . . . . . . Structured Language Source Text
  68.            BSLP.BAS . . . . . . Microsoft Basic Source Code
  69.            BSLP.DOC . . . . . . Documentation
  70.            BSLP.MSD . . . . . . MS-DOS Compiled Version (.EXE)
  71.            BSLP.CPM . . . . . . CP/M 80 Compiled Version (.COM)
  72.  
  73.          Files for BMLP: Basic Macro Language Preprocessor
  74.  
  75.            BMLP.P . . . . . . . Structured Language Source Text
  76.            BMLP.BAS . . . . . . Microsoft Basic Source Code
  77.            BMLP.DOC . . . . . . Documentation
  78.            BMLP.MSD . . . . . . MS-DOS Compiled Version (.EXE)
  79.            BMLP.CPM . . . . . . CP/M 80 Compiled Version (.COM)
  80.  
  81.          Files for BSLP & BMLP example programs
  82.  
  83.            XFRAME.M . . . . . . Example Program Source Text
  84.            XFRAME.ML  . . . . . Library for XFRAME.M
  85.            BINPUT.M . . . . . . Example Program Source Text
  86.            BINPUT.ML  . . . . . Library for BINPUT.M
  87.  
  88.  
  89. BMLP.DOC
  90.  
  91.        Function
  92.  
  93.          BMLP  expands macro expressions using program resident and/or 
  94.          library file macro definitions.  BMLP  is  written  in  'SSS' 
  95.          language and should be a useful learning tool.  
  96.  
  97.     
  98.        Invocation
  99.  
  100.          Entering 'BMLP' at the DOS prompt will  envoke  the  compiled 
  101.          version  (.EXE)  of BMLP.  The (.BAS) version will have to be 
  102.          run using the interpreter by entering 'BASICA  BMLP'  at  the 
  103.          DOS  prompt.  BMLP  will  then prompt for the input file name 
  104.          and the output file name.  The default  for  the  input  file 
  105.          extension  is '.M',  and the default for the output file name 
  106.          is the input file name with the extension of '.P'.  
  107.  
  108.  
  109.        Formats è
  110.             Macro expression format: 
  111.  
  112.                  $macro-name param1,param2,param3 
  113.          
  114.          A leading dollar sign ($) is used to identify  a  macro  name 
  115.          and,  except for spaces and tabs, must be the first character 
  116.          on  the  line.   When  parameters  are  used,  they  must  be 
  117.          separated by a comma, tab, or space;  when there are too many 
  118.          to put on one line,  a double backslash (\\) may be  used  to 
  119.          continue on the next line.  
  120.  
  121.  
  122.             Macro coding format:
  123.  
  124.                  MACRO <macro-name>
  125.                  ENDM
  126.              
  127.          Macros  are  written and maintained with a text editor in one 
  128.          or more library  text  files  and/or  program  source  files.  
  129.          Macro  names may contain any combination of characters except 
  130.          commas,   tabs,   and  spaces,   and   there   is   no   case 
  131.          discrimination.  The  keyword  'MACRO'  is used to identify a 
  132.          macro name and the beginning of code  for  that  macro  name.  
  133.          The  keyword  'ENDM'  identifies  the end of code for a macro 
  134.          name.  Within the macro code a number enclosed with  brackets 
  135.          ([])  identifies  a  parameter request.  A leading semi-colon 
  136.          (;) may be used as a comment character.  Macros may use other 
  137.          macros as  well  as  supporting  subroutines  (more  on  this 
  138.          later).  
  139.  
  140. 
  141.  
  142.        Design
  143.  
  144.  
  145.          Writing macros is easy, fun and can be habit forming once you 
  146.          get  the  hang  of  it.  To demonstrate let's take the simple 
  147.          task of displaying text on the video monitor.  The  following 
  148.          list of operations describes this task in detail: 
  149.          
  150.  
  151.             1. Save the current cursor location.
  152.             2. Turn off and re-position the cursor.
  153.             3. Clear a space the size of the text.
  154.             4. Re-position the cursor.
  155.             5. Display the text.
  156.             6. Restore cursor location and turn it on.
  157.  
  158.  
  159.          BASIC code for this example might be:
  160.  
  161.             100 XR%=CSRLIN:XC%=POS(0)
  162.                 :LOCATE,,0:LOCATE ROW,COL
  163.                 :PRINT SPACE$(LEN(TEXT$));
  164.                 :LOCATE ROW,COL
  165.                 :PRINT TEXT$;
  166.                 :LOCATE XR%,XC%,1
  167.       
  168.          A macro expression for the above example:
  169.       
  170.             $CRT ROW,COL,TEXT$
  171.             /--- -------------\
  172.             Macro Name         Parameter List
  173.       
  174.          Code for the 'CRT' macro could be written like this:
  175.       
  176.             MACRO CRT
  177.                XR%=CSRLIN:XC%=POS(0)
  178.                LOCATE,,0:LOCATE [1],[2],0:PRINT SPACE$(LEN([3]));
  179.                LOCATE [1],[2],0:PRINT [3];:LOCATE XR%,XC%,1
  180.             ENDM
  181. 
  182.  
  183.       
  184.          The  parameters  are  numbered in left to right order as they 
  185.          appear in the list following the 'CRT' macro, e.g.; 
  186.  
  187.  
  188.             [1] = ROW     <parameter one>
  189.             [2] = COL     <parameter two>
  190.             [3] = TEXT$   <parameter three>
  191.  
  192.          Parameters  can  be  passed  using   variables   or   literal 
  193.          expressions: 
  194.  
  195.             $CRT 12,10,"Hello World!"
  196.  
  197.  
  198.  
  199.        Nesting Macros
  200.   
  201.          Because  a  macro  can use other macros (nesting),  the 'CRT' 
  202.          macro can also be written using macros for the  required  six 
  203.          functions.  
  204.  
  205.  
  206.             1. Save the current cursor location. ------+
  207.             |  MACRO SVC                               |
  208.             |      [1]=CSRLIN:[2]=POS(0)               |
  209.             |  ENDM                                    |
  210.             +------------------------------------------+
  211.  
  212.             2. Position the cursor and switch on/off. -+
  213.             |  MACRO XY                                |
  214.             |      LOCATE [1],[2],[3]                  |
  215.             |  ENDM                                    |
  216.             +------------------------------------------+
  217.  
  218.             3. Clear a space the size of the text. ----+
  219.             |  MACRO CLR                               |
  220.             |      PRINT SPACE$([1]);                  |
  221.             |  ENDM                                    |
  222.             +------------------------------------------+
  223.  
  224.             4. Re-position the cursor. ----------------+
  225.             |  (Use the XY macro, (2))                 |
  226.             +------------------------------------------+
  227.  
  228.             5. Display the text. ----------------------+
  229.             |  MACRO SHO                               |
  230.             |      PRINT [1];                          |
  231.             |  ENDM                                    |
  232.             +------------------------------------------+
  233.  
  234.             6. Restore cursor location, turn it on. ---+ 
  235.             |  (Again use the XY macro, (2))           |è            +------------------------------------------+
  236. 
  237.  
  238.          Now the 'CRT' macro can be written using the four new macros:
  239.  
  240.             MACRO CRT                
  241.                 $SVC XR%,XC% 
  242.                 $XY ,,0
  243.                 $XY [1],[2],0
  244.                 $CLR LEN([3])
  245.                 $XY [1],[2],0
  246.                 $SHO [3]
  247.                 $XY XR%,XC%,1
  248.             ENDM
  249.                 
  250.          Writing  macros  for  the  lower level functions of the 'CRT' 
  251.          macro provides  several  benefits,  one  of  them  being  the 
  252.          availability  of  lower  level  macros  to be used in writing 
  253.          other higher level macros.  
  254.  
  255.  
  256.        Conditional Logic
  257.  
  258.             $IF / $ELSE / $END
  259.     
  260.          '$IF-$ELSE-$END' are reserved macro keywords that provide the 
  261.          ability to control the inclusion or expansion of segments  of 
  262.          code  within  a  macro.  The 'CRT' macro can be enhanced with 
  263.          added ability to display the text in reverse video.  This  is 
  264.          easily  implemented  using a fourth parameter and conditional 
  265.          logic to control the inclusion of the "COLOR" statement.  
  266.  
  267.  
  268.             MACRO CRT
  269.                 $SVC XR%,XC%
  270.                 $XY ,,0
  271.                 $XY [1],[2],0
  272.                 $CLR LEN([3])
  273.                 $XY [1],[2],0
  274.                 $IF [4]     <--+  If fourth parameter ([4]) is provided
  275.                 COLOR 0,7      |  then the statement 'COLOR 0,7' will
  276.                 $END        <--+  be included. (Reverse)
  277.                 $SHO [3]
  278.                 $IF [4]     <--+  If fourth parameter ([4]) is provided
  279.                 COLOR 7,0      |  then the statement 'COLOR 7,0' will
  280.                 $END        <--+  be included. (Reset to Normal)
  281.                 $XY XR%,XC%,1
  282.             ENDM
  283. 
  284.  
  285.          Example:
  286.  
  287.             $CRT 12,10,"Hello World!",REV
  288.                                         \..(fourth parameter)
  289.             (Display "Hello World!" at row 12, column 10, in reverse video.)
  290.  
  291.             $CRT 12,10,"Hello World!"
  292.                                         \..(missing fourth parameter)
  293.             (Display "Hello World!" at row 12, column 10, in normal video.)
  294.   
  295.  
  296.  
  297.        Logical Operators
  298.  
  299.          The 'equal-to (=)' and the 'not-equal (#)  or  (<>)'  logical 
  300.          operators  can  be  used  to  test  literal  parameters for a 
  301.          specific value, e.g.; 
  302.       
  303.  
  304.             $IF [1] = 1
  305.             $IF [6] # NOERROR
  306.             $IF [4] = REV
  307.                     \
  308.                     (Operators must to be separated by spaces or tabs.)
  309.  
  310.          'CRT' macro with logical operators: 
  311.  
  312.             MACRO CRT
  313.                 $SVC XR%,XC%
  314.                 $XY ,,0
  315.                 $XY [1],[2],0
  316.                 $CLR LEN([3])
  317.                 $XY [1],[2],0
  318.                 $IF [4] = REV  <--+  If fourth parameter ([4]) EQUALS "REV"
  319.                 COLOR 0,7         |  then the statement 'COLOR 0,7' will
  320.                 $END           <--+  be included. (Reverse)
  321.                 $SHO [3]
  322.                 $IF [4] # NORM <--+  If fourth parameter ([4]) NOT EQUAL "NORM"
  323.                 COLOR 7,0         |  then the statement 'COLOR 7,0' will
  324.                 $END           <--+  be included. (Reset to Normal)
  325.                 $XY XR%,XC%,1
  326.             ENDM
  327.  
  328.          Example:
  329.  
  330.             $CRT 12,10,"Hello World!",REV
  331.                                         \..(fourth parameter)
  332.             (Display "Hello World!" at row 12, column 10, in reverse video.)
  333.  
  334.             $CRT 12,10,"Hello World!",NORM
  335.                                         \..(fourth parameter)
  336.             (Display "Hello World!" at row 12, column 10, in normal video.)
  337. 
  338.  
  339.        Macros and Subroutines
  340.  
  341.          One of the more powerful features of macro programming is the 
  342.          ability to write macros that require supporting  subroutines.  
  343.          This  ability  allows  the use of a macro any number of times 
  344.          within a program,  with only one inclusion of its  supporting 
  345.          subroutine.  Thus, blocks of duplicated code are eliminated.  
  346.  
  347.  
  348.          An example is the operation of stripping leading and trailing 
  349.          space and tab characters from a string of text: 
  350.  
  351.       
  352.          $STRIP TEXT$
  353.       
  354.          The code for 'STRIP' macro:------+
  355.          MACRO STRIP                      |
  356.              X$=[1]:Gosub _Stripit:[1]=X$ |
  357.              $$_STRIP                     |
  358.          ENDM                             |
  359.          ---------------------------------+
  360.        
  361.          The code for '_STRIP' supporting subroutine:----------------+
  362.          MACRO _STRIP                                                |
  363.          proc _Stripit                                               |
  364.              unless LEN(X$)<3                                        |
  365.                  X%=LEN(X$)+1                                        |
  366.                  WHILE(X%>LEN(X$) AND LEN(X$)>2)                     |
  367.                      X%=LEN(X$)                                      |
  368.                      X$=LEFT$(X$,LEN(X$)+(RIGHT$(X$,1)=" "))         |
  369.                      X$=LEFT$(X$,LEN(X$)+(ASC(RIGHT$(X$,1))=9))      |
  370.                      X$=RIGHT$(X$,LEN(X$)+(ASC(X$)=32 OR ASC(X$)=9)) |
  371.                  WEND                                                |
  372.              endu                                                    |
  373.          endp                                                        |
  374.          ENDM                                                        |
  375.          ------------------------------------------------------------+
  376.               
  377.          The  leading  double  dollar sign ($$) identify '_STRIP' as a 
  378.          subroutine which is defined as a procedure (_Stripit) and  it 
  379.          will be included into a program source file only one time.  A 
  380.          subroutine may include and use other subroutines and macros.  
  381.  
  382. 
  383.  
  384.        Developing Libraries
  385.  
  386.          Macros can be written within a  program  source  file,  where 
  387.          they can be easily tested and debugged before being committed 
  388.          to  a  library  file.   Library  documentation  is  extremely 
  389.          important.  After  writing  a  couple  of  dozen  macros,  it 
  390.          becomes  a  little  more  difficult  to remember function and 
  391.          parameter requirements for each macro.  The ability to  share 
  392.          libraries  among  several  programmers  working  on  the same 
  393.          project makes the library documentation essential.  
  394.  
  395.  
  396.        Using Libraries
  397.  
  398.             LIBRARY <file-name.ext>
  399.  
  400.          The keyword 'LIBRARY' is used at the top of a program  source 
  401.          file to identify each macro library to use in processing that 
  402.          source  file.  Libraries can be nested by specifing libraries 
  403.          within libraries.  
  404.  
  405.  
  406. BMLP.BAS
  407.  
  408. 100 SIGN$    = "$"
  409. 101 DOT$     = "."
  410. 102 OEXT$    = ".P"         ' Output file default extension
  411. 103 IEXT$    = ".M"         ' Input file default extension
  412. 104 LEXT$    = ".ML"        ' Library file default extension
  413. 105 SOURCE%  = 2            ' Input file number
  414. 106 O.FILE%  = 1            ' Output file number
  415. 107 I.FILE%  = 2
  416. 108 ERRORS%  = 0
  417. 109 FALSE%   = 0
  418. 110 TRUE%    = NOT FALSE%
  419. 111 EXPAND%  = TRUE%
  420. 112 STORE.%  = 0
  421. 113 NEST%    = 1
  422. 114 DIM FILE.%(50)      ' TEMPORARY STACK OF POINTERS TO THE NEXT SUBSCRIPT
  423. 115 DIM PARM$(500)      ' TEMPORARY STORAGE OF PARAMETERS TO PASS TO MACROS.
  424. 116 DIM PARM%(100)      ' ARRAY OF POINTERS TO PARAMETER STORAGE.
  425. 117 DIM MACRO$(100)     ' STORAGE FOR MACRO NAMES.
  426. 118 DIM MACRO%(100)     ' ARRAY OF POINTERS TO FIRST CODE LOCATION IN STORE$ ARRAY
  427. 119 DIM STORE$(1000)    ' STORAGE FOR MACRO TEXT.
  428. 120 DIM SUBS$(50)       ' STORAGE FOR MACRO SUBROUTINE NAMES.
  429. 121 PRINT "BMLP   V1.0B (C) BENDORF ASSOCIATES, 1984-85"
  430. 122 PRINT
  431. 123 GoSub 354
  432. 124 IF NOT(I.FILE%>0) GOTO 133
  433. 125 GoSub 137
  434. 126 CLOSE
  435. 127 IF NOT(ERRORS%>0) GOTO 131
  436. 128 KILL O.FILE$è129 PRINT O.FILE$;" ABORTED WITH ";STR$(ERRORS%);" ERROR(S)."
  437. 130 GOTO 132
  438. 131 PRINT"<";O.FILE$;"> DONE!"
  439. 132 GOTO 135
  440. 133 IF NOT(I.FILE$<>"") GOTO 135
  441. 134 PRINT"CANNOT OPEN ";I.FILE$
  442. 135 END
  443. 136     'PROCESS-SOURCE-FILE
  444. 137 OPEN"O",O.FILE%,O.FILE$
  445. 138 OPEN"I",I.FILE%,I.FILE$
  446. 139 FILE.%(NEST%)=-1
  447. 140 IF(NEST%=0) GOTO 175
  448. 141 while ENDOFF%=FALSE%
  449. 142 GoSub 267
  450. 143 IF NOT(LN.%>1 AND ENDOFF%=FALSE%) GOTO 147
  451. 144 GoSub 207
  452. 145 GoSub 177
  453. 146 GOTO 149
  454. 147 IF NOT(SKIP% AND I.FILE%=SOURCE%) GOTO 149
  455. 148 PRINT #O.FILE%,BUF$
  456. 149 wend
  457. 150 IF(NEST%=1)THEN FIRST%=0 ELSE FIRST%=PARM%(NEST%-1)
  458. 151 LAST%=PARM%(NEST%)
  459. 152 PARM%(NEST%)=0
  460. 153 while (FIRST%<LAST%)
  461. 154 PARM$(LAST%)=""
  462. 155 LAST%=LAST%-1
  463. 156 wend
  464. 157 IF NOT(FILE.%(NEST%)<0 AND NEST%>1 AND I.FILE%>SOURCE%) GOTO 161
  465. 158 CLOSE #I.FILE%
  466. 159 I.FILE%=I.FILE%-1
  467. 160 GOTO 162
  468. 161 POINTER%=FILE.%(NEST%-1)
  469. 162 NEST%=NEST%-1
  470. 163 ENDOFF%=FALSE%
  471. 164 IF(NEST%>0 OR SUBS%=LAST.S%) GOTO 174
  472. 165 LAST.S%=LAST.S%+1
  473. 166 TEXT$=SUBS$(LAST.S%)
  474. 167 GoSub 301
  475. 168 IF NOT(FOUND%) GOTO 172
  476. 169 FILE.%(NEST%+1)=FIND%:POINTER%=FIND%
  477. 170 NEST%=NEST%+1
  478. 171 GOTO 174
  479. 172 EBUF$="SUBROUTINE ("+TEXT$+") NOT FOUND!"
  480. 173 GoSub 367
  481. 174 IF(NEST%>0) GOTO 140
  482. 175 RETURN
  483. 176     'PARSE-INPUT-LINE
  484. 177 GoSub 334
  485. 178 GoSub 372
  486. 179 IF NOT(LEFT$(TEXT$,1)=SIGN$) GOTO 197
  487. 180 TEXT$=RIGHT$(TEXT$,LEN(TEXT$)-1)
  488. 181 IF NOT(TEXT$="if") GOTO 184
  489. 182 GoSub 220
  490. 183 GOTO 196è184 IF NOT(TEXT$="else") GOTO 187
  491. 185 EXPAND%=(EXPAND%=FALSE%)
  492. 186 GOTO 196
  493. 187 IF NOT(TEXT$="end") GOTO 190
  494. 188 EXPAND%=TRUE%
  495. 189 GOTO 196
  496. 190 IF NOT(LEFT$(TEXT$,1)=SIGN$) GOTO 194
  497. 191 TEXT$=RIGHT$(TEXT$,LEN(TEXT$)-1)
  498. 192 GoSub 395
  499. 193 GOTO 196
  500. 194 IF NOT(EXPAND%) GOTO 196
  501. 195 GoSub 241
  502. 196 GOTO 205
  503. 197 IF NOT(TEXT$="macro") GOTO 200
  504. 198 GoSub 309
  505. 199 GOTO 205
  506. 200 IF NOT(TEXT$="library") GOTO 203
  507. 201 GoSub 379
  508. 202 GOTO 205
  509. 203 IF NOT(EXPAND% AND I.FILE%=SOURCE%) GOTO 205
  510. 204 PRINT #O.FILE%,BUF$
  511. 205 RETURN
  512. 206     'INSERT-PARAMETERS
  513. 207 LB%=INSTR(1,BUF$,"[")
  514. 208 while (LB%>0)
  515. 209 RB%=INSTR(LB%,BUF$,"]")
  516. 210 IF NOT(RB%>0) GOTO 215
  517. 211 INSERT$=PARM$(PARM%(NEST%-1)+VAL(MID$(BUF$,LB%+1,RB%-LB%)))
  518. 212 BUF$=LEFT$(BUF$,LB%-1)+INSERT$+RIGHT$(BUF$,LEN(BUF$)-RB%)
  519. 213 LB%=INSTR(RB%,BUF$,"[")
  520. 214 GOTO 216
  521. 215 LB%=0
  522. 216 wend
  523. 217 LN.%=LEN(BUF$)
  524. 218 RETURN
  525. 219     'SET-CONDITIONAL
  526. 220 GoSub 334
  527. 221 L$=TEXT$:OP$=""
  528. 222 IF(L$="=" OR L$="#" OR L$="<>")THEN OP$=L$:L$=""
  529. 223 GoSub 334
  530. 224 IF NOT(TEXT$="") GOTO 227
  531. 225 OP$="<>":R$=""
  532. 226 GOTO 231
  533. 227 IF NOT(OP$="") GOTO 231
  534. 228 OP$=TEXT$
  535. 229 GoSub 334
  536. 230 R$=TEXT$
  537. 231 IF NOT(OP$="=") GOTO 234
  538. 232 EXPAND%=(R$=L$)
  539. 233 GOTO 239
  540. 234 IF NOT(OP$="<>" OR OP$="#") GOTO 237
  541. 235 EXPAND%=(R$<>L$)
  542. 236 GOTO 239
  543. 237 EBUF$="ILLEGAL OPERATOR("+OP$+")"
  544. 238 GoSub 367è239 RETURN
  545. 240     'EXPAND-MACRO
  546. 241 GoSub 301
  547. 242 IF NOT(FOUND%) GOTO 250
  548. 243 IF(FILE.%(NEST%)=>0)THEN FILE.%(NEST%)=POINTER%
  549. 244 POINTER%=FIND%
  550. 245 NEST%=NEST%+1
  551. 246 FILE.%(NEST%)=FIND%
  552. 247 PARM%(NEST%)=PARM%(NEST%-1)
  553. 248 GoSub 254
  554. 249 GOTO 252
  555. 250 EBUF$="MACRO ("+TEXT$+") NOT DEFINED."
  556. 251 GoSub 367
  557. 252 RETURN
  558. 253     'LOAD-PARAMETERS
  559. 254 PASS%=FALSE%
  560. 255 while PASS%=FALSE%
  561. 256 PASS%=(CON%=FALSE%)
  562. 257 GoSub 334
  563. 258 while (FIRST%<=LN.%)
  564. 259 PARM%(NEST%)=PARM%(NEST%)+1
  565. 260 PARM$(PARM%(NEST%))=TEXT$
  566. 261 GoSub 334
  567. 262 wend
  568. 263 IF(CON%)THEN GoSub 279
  569. 264 wend
  570. 265 RETURN
  571. 266     'INPUT-BUFFER
  572. 267 IF NOT(FILE.%(NEST%)<0) GOTO 270
  573. 268 GoSub 279
  574. 269 GOTO 277
  575. 270 BUF$=STORE$(POINTER%)
  576. 271 POINTER%=POINTER%+1
  577. 272 ENDOFF%=(BUF$=CHR$(7))
  578. 273 SKIP%=FALSE%
  579. 274 CON%=SKIP%
  580. 275 LN.%=LEN(BUF$)
  581. 276 INDEX%=0
  582. 277 RETURN
  583. 278     'INPUT-SOURCE
  584. 279 INDEX%=0:CON%=FALSE%
  585. 280 LINE INPUT #I.FILE%,BUF$
  586. 281 ENDOFF%=EOF(I.FILE%)
  587. 282 LN.%=LEN(BUF$):I%=1:II%=0
  588. 283 while (I%>II% AND I%<LEN(BUF$))
  589. 284 II%=I%:I%=I%+ABS(MID$(BUF$,I%,1)=" " OR MID$(BUF$,I%,1)=CHR$(9))
  590. 285 wend
  591. 286 II%=LN.%+1
  592. 287 while (II%>LN.% AND LN.%>I%)
  593. 288 II%=LN.%:LN.%=LN.%+(MID$(BUF$,LN.%,1)=" " OR MID$(BUF$,LN.%,1)=CHR$(9))
  594. 289 wend
  595. 290 BUF$=MID$(BUF$,I%,LN.%):LN.%=LEN(BUF$)
  596. 291 SKIP%=(MID$(BUF$,1,1)="'" OR MID$(BUF$,1,1)=";" OR LEN(BUF$)<2)
  597. 292 IF NOT(SKIP%) GOTO 295
  598. 293 LN.%=1è294 GOTO 299
  599. 295 IF NOT(RIGHT$(BUF$,2)="\\") GOTO 299
  600. 296 CON%=TRUE%
  601. 297 BUF$=LEFT$(BUF$,LEN(BUF$)-2)
  602. 298 LN.%=LEN(BUF$)
  603. 299 RETURN
  604. 300     'FIND-MACRO-NAME
  605. 301 FIND%=FALSE%:THIS.M%=0
  606. 302 FOR M%=1 TO LAST.M%
  607. 303 IF(MACRO$(M%)=TEXT$)THEN THIS.M%=M%:M%=LAST.M%+1
  608. 304 NEXT M%
  609. 305 FOUND%=(THIS.M%>0)
  610. 306 IF(FOUND%)THEN FIND%=MACRO%(THIS.M%)
  611. 307 RETURN
  612. 308     'INPUT-A-MACRO
  613. 309 GoSub 334
  614. 310 GoSub 372
  615. 311 GoSub 301
  616. 312 IF NOT(FOUND%) GOTO 315
  617. 313 MACRO%(THIS.M%)=STORE.%+1
  618. 314 GOTO 318
  619. 315 MACRO$(LAST.M%+1)=TEXT$
  620. 316 MACRO%(LAST.M%+1)=STORE.%+1
  621. 317 LAST.M%=LAST.M%+1
  622. 318 GoSub 279
  623. 319 GoSub 334
  624. 320 GoSub 372
  625. 321 while (TEXT$<>"endm" AND ENDOFF%=FALSE%)
  626. 322 IF(SKIP%=FALSE%)THEN GoSub 330
  627. 323 GoSub 279
  628. 324 IF(SKIP%=FALSE%)THEN GoSub 334:GoSub 372
  629. 325 wend
  630. 326 BUF$=CHR$(7)
  631. 327 GoSub 330
  632. 328 RETURN
  633. 329     'STORE-MACRO-CODE
  634. 330 STORE.%=STORE.%+1
  635. 331 STORE$(STORE.%)=BUF$
  636. 332 RETURN
  637. 333     'PARSER
  638. 334 I%=32
  639. 335 while (I%=32)
  640. 336 INDEX%=INDEX%+1
  641. 337 IF(INDEX%<=LEN(BUF$))THEN I%=ASC(MID$(BUF$,INDEX%,1)) ELSE I%=7
  642. 338 I%=I%+(23*ABS(I%=9))
  643. 339 wend
  644. 340 FIRST%=INDEX%
  645. 341 while (I%<>32 AND I%<>7)
  646. 342 IF NOT(I%=44 OR I%=9) GOTO 345
  647. 343 I%=32
  648. 344 GOTO 350
  649. 345 IF NOT(I%=34) GOTO 348
  650. 346 X%=INSTR(INDEX%+1,BUF$,CHR$(34))
  651. 347 IF(X%>INDEX%)THEN INDEX%=X%
  652. 348 INDEX%=INDEX%+1è349 IF(INDEX%<=LEN(BUF$))THEN I%=ASC(MID$(BUF$,INDEX%,1)) ELSE I%=7
  653. 350 wend
  654. 351 TEXT$=MID$(BUF$,FIRST%,INDEX%-FIRST%)
  655. 352 RETURN
  656. 353     'FILENAMES
  657. 354 LINE INPUT"INPUT FILE [.M]:",I.FILE$
  658. 355 IF(I.FILE$="") GOTO 365
  659. 356 IF(INSTR(I.FILE$,DOT$)=0)THEN I.FILE$=I.FILE$+IEXT$
  660. 357 LK.$=I.FILE$:LK.%=I.FILE%:GoSub 391:I.FILE%=LK.%
  661. 358 IF(I.FILE%=FALSE%) GOTO 365
  662. 359 I%=INSTR(1,I.FILE$,DOT$)
  663. 360 IF(I%=0)THEN I%=LEN(I.FILE$)+1
  664. 361 FILE$=LEFT$(I.FILE$,I%-1)
  665. 362 LINE INPUT"OUTPUT FILE [.P]:",O.FILE$
  666. 363 IF(O.FILE$="")THEN O.FILE$=FILE$
  667. 364 IF(INSTR(O.FILE$,DOT$)=0)THEN O.FILE$=O.FILE$+OEXT$
  668. 365 RETURN
  669. 366     'ERRORS
  670. 367 ERRORS%=ERRORS%+1
  671. 368 EBUF$="ERR#"+STR$(ERRORS%)+" ("+EBUF$+")"
  672. 369 PRINT EBUF$
  673. 370 RETURN
  674. 371     'LCASE
  675. 372 I%=1
  676. 373 while (I%<=LEN(TEXT$))
  677. 374 II%=ASC(MID$(TEXT$,I%,1))
  678. 375 MID$(TEXT$,I%,1)=CHR$(II%+(32*ABS(II%>64 AND II%<91))):I%=I%+1
  679. 376 wend
  680. 377 RETURN
  681. 378     'LIBRARY
  682. 379 GoSub 334
  683. 380 IF(TEXT$="") GOTO 389
  684. 381 IF(INSTR(TEXT$,DOT$)=0)THEN TEXT$=TEXT$+LEXT$
  685. 382 LK.%=I.FILE%+1:LK.$=TEXT$:GoSub 391
  686. 383 IF NOT(LK.%>0) GOTO 387
  687. 384 OPEN"I",LK.%,LK.$:I.FILE%=LK.%
  688. 385 NEST%=NEST%+1:FILE.%(NEST%)=-1
  689. 386 GOTO 389
  690. 387 EBUF$="LIBRARY ("+LK.$+") NOT FOUND!"
  691. 388 GoSub 367
  692. 389 RETURN
  693. 390     '_Lookup
  694. 391 OPEN"R",LK.%,LK.$:L.K!=LOF(LK.%):CLOSE LK.%
  695. 392 IF(L.K!<1)THEN LK.%=0:KILL LK.$
  696. 393 RETURN
  697. 394     'SUBROUTINE
  698. 395 S%=0
  699. 396 while (S%<SUBS%)
  700. 397 S%=S%+1:IF(TEXT$=SUBS$(S%))THEN S%=SUBS%+1
  701. 398 wend
  702. 399 IF(S%=SUBS%)THEN SUBS%=SUBS%+1:SUBS$(SUBS%)=TEXT$
  703. 400 RETURN
  704.  
  705. èBINPUT.M
  706.  
  707. '------------------------------------------------------
  708. '-         Standardized Program Shell                 -
  709. '------------------------------------------------------
  710. '- Program:BINPUT
  711. '- System :PPE TOOLS
  712. '- Module :BMLP
  713. '- Task   :EXAMPLE SOURCE TO BE PREPROCESSED BY BMLP & BSLP
  714. '- Created:3.3.85
  715. '- By     :D. L. Bendorf
  716. '- Version:N/A
  717. '- Notes  :LIBRARY <BINPUT.ML>
  718. '- History:               
  719. '-
  720. '------------------------------------------------------
  721. '- ** Data Division                                   -
  722. '------------------------------------------------------
  723. LIBRARY BINPUT
  724. '------------------------------------------------------
  725. T.R%       = 1    'ROW for time display
  726. T.C%       = 50    'COLUMN  
  727. TIMEFLAG%  = 1     'enable time display 
  728. ENTRYFLAG% = 1    'enable keyboard input
  729.  
  730. MACRO DO
  731.     GoSub [1]
  732. ENDM
  733. '------------------------------------------------------
  734. '- ** Procedure Division                              -
  735. '------------------------------------------------------
  736. PROG BINPUT
  737.     $DO Screen
  738.  
  739.     LOOP
  740.         $DO Form
  741.     ENDL WHEN EDITFLAG%<>1 OR ABORTFLAG%<>0
  742.  
  743.     WHEN ABORTFLAG%=0    
  744.         ENTRYFLAG%=0         'Set display mode on
  745.         $DO Form            
  746.         'Go display data
  747.     ENDW
  748. PEND
  749. PROC Form
  750.     REPEAT
  751.         $INPUT 1,NAMES$,8,10,40,"U","E","",NAMES$,"R","",""
  752.         $INPUT 2,AGE$,8,58,2,"N","E","",AGE$,"R","",""
  753.         $INPUT 3,SEX$,8,67,1,"V","E","",SEX$,"MF","",""
  754.         $INPUT 4,ADDRESS$,10,13,25,"U","E","",ADDRESS$,"R","",""
  755.         $INPUT 5,CITY$,10,47,15,"U","E","",CITY$,"R","",""
  756.         $INPUT 6,STATE$,10,71,2,"U","E","",STATE$,"R","",""
  757.         $INPUT 7,ZIPCODE$,12,13,10,"N","E","",ZIPCODE$,"R","",""
  758.         $INPUT 8,PHONE$,12,32,10,"N","E","(???)-???-????",PHONE$,"R","",""
  759.         $INPUT 9,BIRTH$,12,60,6,"D","E","??/??/??",BIRTH$,"R","",""è        EDITFLAG%=0            'Shutoff edit mode
  760.  
  761.         UNLESS ENTRYFLAG%=0
  762.             $PROMPT "Any Changes?","YN"+CHR$(13),EDITFLAG%
  763.             WHO%=1            'Set for field #1 case edit mode
  764.         ENDU
  765.  
  766.     UNTIL EDITFLAG%<>1
  767. ENDP
  768. PROC Screen
  769.     key off
  770.     $Video
  771.     $Frame 6,14,1,79
  772.     $Crt 08,03," Name:",1
  773.     $Crt 08,52," Age:"
  774.     $Crt 08,61," Sex:"
  775.     $Crt 10,03," Address:"
  776.     $Crt 10,40," City:"
  777.     $Crt 10,63," State:"
  778.     $Crt 12,03," ZipCode:"
  779.     $Crt 12,24," Phone:"
  780.     $Crt 12,47," Birth-Date:",,1
  781. ENDP
  782. '------------------------------------------------------
  783. '- ** SubRoutine Division                             -
  784. '------------------------------------------------------
  785.  
  786.  
  787. BINPUT.ML
  788.  
  789. ;;==========================================================================
  790. ; NOTE:
  791. ;         THE `|' VERTICAL BAR IS USED AS A CONTINUATION MARK.
  792. ; DOCUMENTATION ABREVIATIONS:
  793. ;         S/L  =  STRING VARIABLE OR LITERAL ENCLOSED WITH DOUBLE QUOTES.
  794. ;         N/L  =  NUMERIC VARIABLE OR LITERAL.
  795. ;         S    =  STRING VARIABLE ONLY.
  796. ;         N    =  NUMERIC VARIABLE ONLY.         
  797. ;         S/N  =  STRING OR NUMERIC VARIABLE.
  798. ;         
  799. ==========================================================================
  800. ;**
  801. ::INPUT (Macro)
  802. ;**   FUNCTION:
  803. ;**             Standard Terminal Input Subroutine.
  804. ;**   USAGE:
  805. ;**             Twelve parameters required.
  806. ;**     Calling:
  807. ;**                [1]   N/L      -   input order index. 
  808. ;**                [2]   S        -   input/display buffer.
  809. ;**                [3]   N/L      -   cursor row to input-display on.
  810. ;**                [4]   N/L      -   cursor column to input-display on.
  811. ;**                [5]   N/L      -   maximum number of input characters.
  812. ;**                [6]   S/L      -   Editing method:
  813. ;**                                   A - any printable character.è;**                                   N - numbers & minus sign.
  814. ;**                                   D - dates with verification.
  815. ;**                                   Y - allows yes/no with conversion.
  816. ;**                                   V - validate input using [10].
  817. ;**                                   U - convert to upper case.
  818. ;**                [7]   S/L      -   allowable exit method:
  819. ;**                                   E - <End> key = abort.
  820. ;**                [8]   S/L      -   display format, eg.`??/??/??'.
  821. ;**                [9]   S/L      -   default for [2] on carriage return.
  822. ;**                [10]  S/L      -   optional input editing feature:
  823. ;**                                   R - required input if no default.
  824. ;**                                   if [6] = "V" [10] must have
  825. ;**                                   a valid string.
  826. ;**                [11]  S/L      -   lower limit for range of numeric input.
  827. ;**                [12]  S/L      -   upper limit for range of numeric input.
  828. ;**     Returning:
  829. ;**                 [2]           -   has unformatted entry.
  830. ;**                ABORTFLAG%     -   entry has been aborted if non-zero.
  831. ;**                XFK%           -   if non-zero a cursor flag will be set
  832. ;**                                   Cursor Flags:
  833. ;**                                      XU.% - up arrow = prior field.
  834. ;**                                      XD.% - down arrow = next field.
  835. ;**
  836. ;**   EXAMPLE:
  837. ;**            $input 1,a$,8,8,1,"Y","E","","Y","","",""
  838. ;**                a$ ="1" if a `Y' or <CR> was entered.
  839. ;**   NOTE:
  840. ;**     Modes:
  841. ;**             The variable ENTRYFLAG% controls the function mode.
  842. ;**   
  843. ;**             Input:   ENTRYFLAG% = 1 : input from keyboard.
  844. ;**                      EDITFLAG%  = 1 : edit - change the contents of [2].
  845. ;**                                     : WHO% controls which item to edit, 
  846. ;**                                       the contents of [2] is formatted 
  847. ;**                                       and displayed on line 24.
  848. ;**             Display: ENTRYFLAG% = 0 : display the contents of [2].
  849. ;**
  850. ;**            This macro requires the _INPUT subroutine. 
  851. ;**            
  852. ;**
  853. MACRO INPUT
  854.    Unless EDITFLAG%=1 And WHO%<>[1]
  855.       XWH%=[1]|
  856.       XEE$=[2]|
  857.       XRW%=[3]|
  858.       XCL%=[4]|
  859.       XLG%=[5]|
  860.       XTY$=[6]|
  861.       XCT$=[7]|
  862.       XFT$=[8]|
  863.       XDF$=[9]|
  864.       XOP$=[10]|
  865.       XLW$=[11]|
  866.       XHI$=[12]|
  867.       Gosub _Input|è      If(ENTRYFLAG%=1)Then If((XAB%+XU.%)<>0)Then Return Else [2]=XEE$
  868.    Endu
  869. ;**
  870. ;**  Include _INPUT subroutine    
  871.    $$_INPUT
  872. ;**
  873. ENDM
  874. ;;==========================================================================
  875. ;**
  876. ::_INPUT (Subroutine)
  877. ;**   FUNCTION:
  878. ;**             Subroutine for support of the INPUT macro.
  879. ;**
  880. MACRO _INPUT
  881. Proc _Input
  882.    XED%=EDITFLAG%
  883.    Unless ENTRYFLAG%<>1
  884.      Gosub _Input_1:If(XAB%<>0)Then Return
  885.      XED%=Abs((XED%+XU.%+XD.%)<>0):If(XED%)Then WHO%=XWH%+(XU.%=1)+ABS(XD.%=1)
  886.      EDITFLAG%=XED%
  887.    Endu
  888.    XTX$=XEE$:If(XTY$="Y")Then If(XEE$="1")Then XTX$="Y"Else XTX$="N"
  889.    $DISPLAY XRW%,XCL%,XTX$,XFT$
  890. Endp
  891. Proc _Input_1
  892.    XFK%=0|
  893.    XU.%=0|
  894.    XD.%=0|
  895.    XAB%=0|
  896.    XLN%=0|
  897.    XH.!=Val(XHI$)|
  898.    XL.!=Val(XLW$)
  899.    Unless XED%=0 Or Len(XEE$)=0
  900.        $DISPLAY 24,XCL%,XEE$,XFT$
  901.    Endu
  902.    XTX$=XEE$
  903.    Unless Len(XEE$)=0
  904.        XTX$="."+XEE$:While(Right$(XTX$,1)=" "):XTX$=Left$(XTX$,Len(XTX$)-1):Wend| 
  905.        XTX$=Mid$(XEE$,1,Len(XTX$)-1):XLN%=Len(XTX$)
  906.    Endu
  907.    If(Len(XTX$)<XLG%)Then XTX$=XTX$+String$(XLG%-Len(XTX$),176)
  908.    XK$=XEE$:If(Len(XEE$)=0)Then XK$=Space$(XLG%)
  909.    Gosub Locate_Input:Gosub _Input_2:ABORTFLAG%=XAB%
  910.    If(XAB%)Then Return Else If(XLN%>0)Then XEE$=XK$
  911.    XEE$=XEE$+Space$(XLG%-Len(XEE$))
  912. Endp
  913. Proc _Input_2
  914.    XZ.%=0|
  915.    XA.%=0|
  916.    While XA.%+XAB%+XFK%=0
  917.       Gosub _InKey
  918.       When XFK%=0
  919.          When XI.%=8 And XZ.%>0
  920.             Print Chr$(29);Chr$(176);Chr$(29);|
  921.             Mid$(XK$,XZ.%,1)=" "|è            XZ.%=XZ.%-1:XLN%=XLN%-1
  922.          Else Unless XI.%<32 Or XI.%>126
  923.             When XTY$="A" Or XI.%=45 Or (XI.%>47 And XI.%<58)
  924.                Gosub _Input_3
  925.             Else Unless Instr("UVY",XTY$)=0
  926.                XI.$=Chr$(XI.%+(32*(XI.%>96 And XI.%<123)))
  927.                When XTY$="V" And (Instr(XOP$,XI.$)=0)
  928.                   $MSG "Invalid Entry!"
  929.                Else
  930.                   Gosub _Input_3
  931.                Endw
  932.             Else
  933.                Beep
  934.             Endw
  935.          Else Unless XI.%<>13
  936.             Gosub Test_Input
  937.          Else
  938.             Beep
  939.          Endw
  940.       Else
  941.          When XFK%=79 And XCT$="E"
  942.             XAB%=1
  943.          Else
  944.             FK%=XFK%
  945.             Switch XFK%
  946.             Case 82
  947.                XFK%=0:X.$=Mid$(XK$,1,XZ.%)+" ":XLN%=XLN%+1|
  948.                X.$=X.$+Mid$(XK$,XZ.%+1,XLG%):XK$=Mid$(X.$,1,XLG%)|
  949.                Gosub New_Display
  950.                Break
  951.             Case 83
  952.                XFK%=0:XK$=Mid$(XK$,1,XZ.%)+Mid$(XK$,XZ.%+2,XLG%)+" ":XLN%=XLN%-1|
  953.                Gosub New_Display
  954.                Break
  955.             Case 72
  956.                XZ.%=0:Gosub Test_Input:XU.%=XK.%
  957.                Break
  958.             Case 75
  959.                XFK%=0:If(XZ.%>0)Then Print Chr$(29);:XZ.%=XZ.%-1:Else Beep
  960.                Break
  961.             Case 77
  962.                XFK%=0:If(XZ.%<XLG%)Then Print Chr$(28);:XZ.%=XZ.%+1:Else Beep
  963.                Break
  964.             Case 80
  965.                XZ.%=0:Gosub Test_Input:XD.%=XK.%
  966.                Break
  967.             Case FK%
  968.                XFK%=0|
  969.                Beep
  970.             Endc
  971.          Endw
  972.       Endw
  973.    Wend
  974. Endp
  975. Proc Locate_Inputè   If(Len(XFT$)<XLG%)Then XFT%=XLG%-Len(XFT$) Else XFT%=1
  976.    Locate XRW%,XCL%,0:Print Space$(Len(XFT$)+XFT%);:Locate XRW%,XCL%|
  977.    Print XTX$;:Locate XRW%,XCL%
  978. Endp
  979. Proc Test_Input
  980.       XK.%=1
  981.       When XZ.%=0 And XOP$="R" And Len(XEE$)=0 And Len(XDF$)=0
  982.             $MSG "Required Entry!"
  983.             XK.%=0:XFK%=0
  984.       Else
  985.          Gosub _Input_4
  986.       Endw
  987. Endp
  988. Proc New_Display
  989.    XR.%=Csrlin:XC.%=Pos(0):Locate XRW%,XCL%,0:Print Space$(XLG%);|
  990.    Locate XRW%,XCL%:Print Mid$(XK$,1,XLN%);String$(XLG%-XLN%,176);:Locate XR.%,XC.%
  991. Endp
  992. Proc _Input_3
  993.    If(XZ.%+1<=XLG%)Then XZ.%=Pos(0)-XCL%+1:Print XI.$;:Mid$(XK$,XZ.%,1)=XI.$:Else Beep
  994.    If(XZ.%>XLN%)Then XLN%=XZ.%
  995. Endp
  996. Proc _Input_4
  997.    When XZ.%=0 And XED%=0 And Len(XDF$)>0
  998.       XK$=XDF$:XZ.%=Len(XDF$)
  999.    Endw
  1000.    XE!=Val(XK$)
  1001.    When XTY$="N" Or XTY$="#"
  1002.       XE.%=((XL.!<>0 And XE!<XL.!) Or (XH.!<>0 And XE!>XH.!))
  1003.       When XE.%<>0
  1004.          $MSG "Out of Range!"
  1005.       Else
  1006.          XA.%=1:If(XE!=0)Then XK$="00":XZ.%=2
  1007.       Endw
  1008.    Else
  1009.       When XTY$="Y"
  1010.          XA.%=1:If(XK$="Y" Or XK$="y")Then XK$="1"Else XK$="2"
  1011.       Else When XTY$="D"
  1012.          Unless Val(XK$)<>0
  1013.             X.$=Date$|
  1014.             XM$=Left$(X.$,2)|
  1015.             XD$=Mid$(X.$,4,2)|
  1016.             XY$=Right$(X.$,2)|
  1017.             XK$=XM$+XD$+XY$
  1018.          Endu
  1019.          XM%=Val(Left$(XK$,2))|
  1020.          XD%=Val(Mid$(XK$,3,2))|
  1021.          When XM%<1 Or XM%>12 Or XD%<1 Or XD%>31
  1022.             $MSG "Enter Date Format MMDDYY"
  1023.          Else
  1024.             XA.%=1
  1025.          Endw
  1026.       Else
  1027.          XA.%=1
  1028.       Endw
  1029.    Endwè   Unless XA.%+XFK%=0
  1030.       $MSG ""
  1031.       Locate 24,1:Print Space$(79);
  1032.    Endu
  1033. Endp
  1034. ;**
  1035. ;**  Here are additional supporting subroutines.
  1036.    $$_FORMAT
  1037.    $$_INKEY
  1038. ENDM
  1039. ;;==========================================================================
  1040. ;**
  1041. ::_INKEY (Subroutine)
  1042. ;**   FUNCTION:
  1043. ;**             Get keyboard input one character at a time.
  1044. ;**   USAGE:
  1045. ;**             Cursor should be positioned before calling.
  1046. ;**             The variable XI.% is returned as decimal value or zero
  1047. ;**             if control/function key was entered,
  1048. ;**             in which case the XFK% variable will be the decimal
  1049. :**             value of entry.
  1050. ;**   NOTE:
  1051. ;**             Basic's INKEY$ function is used to return input from keyboard.
  1052. ;**             Time display will be updated if the variable timeflag%
  1053. ;**             is non-zero.
  1054. ;**           
  1055. MACRO _INKEY
  1056. Proc _InKey
  1057.      ;* call the time display subroutine if non-zero.
  1058.    Unless timeflag%=0
  1059.      ;* the following three variables control time display only.
  1060.       XU%=0|
  1061.       XS%=0|
  1062.       Gosub _Time
  1063.    Endu
  1064.      ;* turn on block cursor
  1065.    Locate ,,1,0,13|
  1066.    XI.$=""|
  1067.      ;* loop here waiting for input and updating the time every second.
  1068.    While XI.$=""|
  1069.       If(timeflag%)Then XU%=XU%+1:If(XU%>GT.%)Then Gosub _Time:XU%=0
  1070.       XI.$=Inkey$
  1071.    Wend|
  1072.    XI.%=Asc(XI.$)|
  1073.      ;* return control or function key if first byte=null.
  1074.    If(XI.%=0)Then XFK%=Asc(Right$(XI.$,1)) Else XFK%=0
  1075. Endp
  1076. ;**
  1077. ;**  Include _TIME subroutine.
  1078.    $$_TIME
  1079. ;**
  1080. ENDM
  1081. ;;==========================================================================
  1082. ;**
  1083. ::_TIME (Subroutine)è;**   FUNCTION:
  1084. ;**             Display time-of-day.
  1085. ;**   USAGE:
  1086. ;**             The display location is controlled by the variables
  1087. ;**             T.r% (row) and T.c% (column). 
  1088. ;**             T.r% and T.c% are set prior to calling.
  1089. ;**   NOTE:
  1090. ;**             GT.% is used by _INKEY to control update frequency.
  1091. ;**             GT.% = 60 - for interpreter.
  1092. ;**             GT.% = 1000 - for compiled.
  1093. ;** 
  1094. MACRO _TIME
  1095. Proc _Time
  1096.    XR.%=Csrlin|
  1097.    XC.%=Pos(0)|
  1098.    XT.$=Time$|
  1099.    XH.%=Val(Left$(XT.$,2))|
  1100.    XM.$=" am"
  1101.    Unless XH.%<12
  1102.       XM.$=" pm":XH%=XH.%+(12*(XH.%>12))|
  1103.       XT.$=Str$(XH%)+Right$(XT.$,Len(XT.$)-Len(Str$(XH.%))+1)|
  1104.       If(XH%=12)Then XM.$=" am"
  1105.    Endu
  1106.    Locate ,,0|  
  1107.    Locate T.R%,T.C%|
  1108.    Print XT.$;XM.$;|
  1109.    Locate XR.%,XC.%,1|
  1110.    XS.%=Val(Right$(XT.$,2))|
  1111.       ;* adjust update frequency if compiled.
  1112.    GT.%=60+(940*ABS(XS.%-XS%=0 And XS%>0))|
  1113.    XS%=XS.%
  1114. Endp
  1115. ENDM
  1116. ;;==========================================================================
  1117. ;**
  1118. ::MSG (Macro)
  1119. ;**   FUNCTION:
  1120. ;**             Display message on line 25 and ding the bell.
  1121. ;**   USAGE:
  1122. ;**             One parameter required.
  1123. ;**             [1] - S/L 
  1124. ;**   EXAMPLE:
  1125. ;**             $msg "HELLO WORLD"
  1126. ;**   NOTE:
  1127. ;**             The current cursor location is saved and then restored after
  1128. ;**             message has been displayed.
  1129. ;**
  1130. MACRO MSG
  1131.    X.$=[1]:Gosub _MSG
  1132. ;**
  1133. ;**  Include the _MSG subroutine.
  1134.    $$_MSG
  1135. ;**
  1136. ENDM
  1137. ;;==========================================================================è;**
  1138. ::_MSG (Subroutine)
  1139. ;**   FUNCTION: Subroutine for the MSG macro.
  1140. ;**
  1141. ;**   NOTE:
  1142. ;**             If X.$ is NULL, line 25 is cleared.
  1143. ;**
  1144. MACRO _MSG
  1145. Proc _MSG
  1146.    XR.%=Csrlin|
  1147.    XC.%=Pos(0)|
  1148.    Locate 25,1,0|
  1149.    Print Space$(79);:If Len(X.$)>0 Then Beep:Locate 25,1:Print X.$;
  1150.    Locate XR.%,XC.%
  1151. Endp
  1152. ENDM
  1153. ;;==========================================================================
  1154. ;**
  1155. ::FORMAT (Macro)
  1156. ;**   FUNCTION: 
  1157. ;**             Format a string using a format description.
  1158. ;**   USAGE:
  1159. ;**             Two parameters are required.
  1160. ;**      Calling:
  1161. ;**             [1] - S   -  containing characters to be formatted.
  1162. ;**             [2] - S/L -  containing a format description.
  1163. ;**      Optional:
  1164. ;**             [3] - L   -  L = left justify
  1165. ;**      Returning:
  1166. ;**             [1] - formatted string.
  1167. ;**
  1168. ;**   EXAMPLE:
  1169. ;**             $format NUMBER$,"###,###.##"
  1170. ;**             $format ACCOUNT$,"????-???",L
  1171. ;**
  1172. ;**   NOTE:
  1173. ;**             Format description characters:
  1174. ;**             # - digit (0..9).
  1175. ;**                 default to "0" if right of decimal point. 
  1176. ;**                 default to " " if left of decimal point.
  1177. ;**             Z - digit (0..9).
  1178. ;**                 default to "0" always.
  1179. ;**             ? - wild card.
  1180. ;**                 default to " " always.
  1181. MACRO FORMAT
  1182.    XTF$=[1]:XFF$=[2]:XJ.$="[3]":Gosub _Format:[1]=XTF$
  1183. ;**   Include _FORMAT subroutine
  1184. ;**
  1185.    $$_FORMAT
  1186. ;**
  1187. ENDM
  1188. ;;==========================================================================
  1189. ;**
  1190. ::_FORMAT (Subroutine)
  1191. ;**   FUNCTION:è;**             Supporting subroutine for FORMAT macro.
  1192. ;**
  1193. ;**
  1194. MACRO _FORMAT
  1195. Proc _Format
  1196.    Unless Len(XFF$)=0 Or Len(XTF$)=0
  1197.       XF1%=Len(XTF$)|
  1198.       XF2%=Len(XFF$)|
  1199.       XXF$=Space$(XF2%)|
  1200.       XF3%=Instr(XFF$,".")|
  1201.       XF4%=(XF3%>0 And Instr(XFF$,"#"))
  1202.       While XF2%+XF1%>0
  1203.          When XF2%>0
  1204.             XF.$=Mid$(XFF$,XF2%,1):XF.%=Instr("?#Z",XF.$)
  1205.             Unless XF.%=0
  1206.                When XF1%>0
  1207.                   XF.$=Mid$(XTF$,XF1%,1)|
  1208.                   If(XF.%>1 And Val(XF.$)=0 And XF.$<>"0")Then XF.$="0" Else XF1%=XF1%-1
  1209.                Else
  1210.                   If(XF.%=3)Then XF.$="0"Else XF.$=" "
  1211.                Endw
  1212.             Endu
  1213.             If(XF.$=" " And XF4% And XF3%>0 And XF2%=>XF3%)Then XF.$="0"
  1214.             Mid$(XXF$,XF2%,1)=XF.$:XF2%=XF2%-1
  1215.          Else
  1216.             XXF$=Mid$(XTF$,XF1%,1)+XXF$:XF1%=XF1%-1
  1217.          Endw
  1218.       Wend
  1219.       While Left$(XXF$,1)=" " And XJ.$="L"
  1220.          XXF$=Right$(XXF$,Len(XXF$)-1)
  1221.       Wend
  1222.       XTF$=XXF$ 
  1223.    Endu
  1224. Endp
  1225. ENDM
  1226. ;;==========================================================================
  1227. ;**
  1228. ::DISPLAY (Macro)
  1229. ;**   FUNCTION:
  1230. ;**             Display on CRT.
  1231. ;**   USAGE:
  1232. ;**             Three parameters are required.
  1233. ;**             One optional parameter.
  1234. ;**     Calling:
  1235. ;**             [1] - N/L - display row (1..24).
  1236. ;**             [2] - N/L - display column (1..80).
  1237. ;**             [3] - S/L - containing characters to be displayed. 
  1238. ;**             [4] - S/L - optional format description.
  1239. ;**
  1240. ;**   EXAMPLE:
  1241. ;**             $display 10,20,"HELLO WORLD"
  1242. ;**             $display RW.%,CL.%,SSN$,"???-??-????"
  1243. ;**             $display 11,25,TODAY$,"??/??/??"
  1244. MACRO DISPLAY
  1245.    XD.$=[3]è;**   if the [4] parameter is used
  1246.    $IF [4]
  1247. ;**   formatting is required.
  1248.    $FORMAT XD.$,[4]
  1249.    $END
  1250.    XR.%=[1]:XC.%=[2]
  1251.    Gosub _Display
  1252. ;**   Include _DISPLAY subroutine
  1253.    $$_DISPLAY
  1254. ;**
  1255. ENDM
  1256. ;;==========================================================================
  1257. ;**
  1258. ::_DISPLAY (Subroutine)
  1259. ;**   FUNCTION:
  1260. ;**             Supporting subroutine for DISPLAY macro.
  1261. ;**
  1262. ;**
  1263. MACRO _DISPLAY
  1264. Proc _Display
  1265.    Locate XR.%,XC.%,0|
  1266.    Print Space$(Len(XD.$)+1);|
  1267.    Locate XR.%,XC.%|
  1268.    Print XD.$;
  1269. Endp
  1270. ENDM
  1271. ;;==========================================================================
  1272. ;**
  1273. ::PROMPT (Macro)
  1274. ;**   FUNCTION:
  1275. ;**             Display a prompt on line 25 and get input from keyboard.
  1276. ;**   USAGE:
  1277. ;**             Two parameters required.
  1278. ;**             Two optional parameters.
  1279. ;**     Calling:
  1280. ;**             [1] - S/L - display message.
  1281. ;**             [2] - S/L - input validation string.
  1282. ;**     Returning:
  1283. ;**      Optional- [3] - N   - index value of input in validation string.
  1284. ;**      Optional- [4] - S   - input character.
  1285. ;**
  1286. ;**   EXAMPLE:
  1287. ;**             $prompt "Any Change","YN",ask.%
  1288. ;**             ask.% = 1 if `Y' entered.
  1289. ;**             ask.% = 2 if `N' entered.
  1290. ;**   NOTE:
  1291. ;**             The current cursor location is saved and restored.
  1292. ;**
  1293. MACRO PROMPT
  1294.    $IF [3]
  1295.    PROMPT$=[1]:XX.$=[2]:Gosub _Prompt:[3]=XX.%
  1296.    $ELSE
  1297.    PROMPT$=[1]:XX.$=[2]:Gosub _Prompt
  1298.    $END
  1299.    $IF [4]è   [4]=XI.$
  1300.    $END
  1301. ;**   Include supporting subroutine.
  1302.    $$_PROMPT
  1303. ;**
  1304. ENDM
  1305. ;;==========================================================================
  1306. ;**
  1307. ::_PROMPT (Subroutine)
  1308. ;**   FUNCTION:
  1309. ;**             Supporting subroutine for PROMPT macro.
  1310. ;**
  1311. MACRO _PROMPT
  1312. Proc _Prompt
  1313.    XR.%=Csrlin|
  1314.    XC.%=Pos(0)|
  1315.    locate 25,1,0:Print PROMPT$;:Locate 25,Pos(0)+1,1,0,13:XI.$=""
  1316.    While(XI.$="")
  1317.       Gosub _InKey|
  1318.       XI.$=Chr$(XI.%+(32*(XI.%>96 And XI.%<123)))|
  1319.       XX.%=Instr(XX.$,XI.$)|
  1320.       If(Len(XX.$)>0)Then If(XX.%=0)Then Beep:XI.$=""
  1321.    Wend
  1322.    Locate 25,1,0|
  1323.    Print Space$(79);|
  1324.    Locate XR.%,XC.%
  1325. Endp
  1326. ;**   Include supporting subroutine.
  1327.    $$_INKEY
  1328. ;**
  1329. ENDM
  1330. ;;==========================================================================
  1331. ;**
  1332. ::FRAME (Macro)
  1333. ;**   FUNCTION:
  1334. ;**             Draws a block graphic frame on screen.
  1335. ;**   USAGE:
  1336. ;**             Four parameters required.
  1337. ;**     Calling:
  1338. ;**             [1] - N/L - top row (1..24).
  1339. ;**             [2] - N/L - bottom row (1..24).
  1340. ;**             [3] - N/L - left column (1..80).
  1341. ;**             [4] - N/L - right column (1..80).
  1342. ;**   EXAMPLE:
  1343. ;**             $frame 4,10,20,60
  1344. ;**             $frame TR%,BR%,LC%,RC%
  1345. ;**             
  1346. MACRO FRAME
  1347.    X1.%=[1]:X2.%=[2]:X3.%=[3]:X4.%=[4]:Gosub _Frame
  1348. ;**   Include supporting subroutine.
  1349.    $$_FRAME
  1350. ;**
  1351. ENDM
  1352. ;;==========================================================================
  1353. ;**è::_FRAME (Subroutine)
  1354. ;**   FUNCTION:
  1355. ;**             Called by FRAME macro to do the work.
  1356. ;**             
  1357. MACRO _FRAME
  1358. Proc _Frame
  1359.    Locate X1.%,X3.%,0|
  1360.    Print Chr$(201);String$(X4.%-X3.%-1,205);Chr$(187);
  1361.    For X5.%=X1.%+1 To X2.%-1|
  1362.    Locate X5.%,X3.%:Print Chr$(186);:Locate X5.%,X4.%:Print Chr$(186);|
  1363.    Next
  1364.    Locate X2.%,X3.%|
  1365.    Print Chr$(200);String$(X4.%-X3.%-1,205);Chr$(188);
  1366. Endp
  1367. ENDM
  1368. ;;==========================================================================
  1369. ;**
  1370. ::VIDEO (Macro)
  1371. ;**   FUNCTION:
  1372. ;**             Routine to get CRT memory offset for color or monochrome,
  1373. ;**             and reset screen and color, and clear screen.
  1374. ;**             Screen:
  1375. ;**                   text mode.
  1376. ;**                   color burst set non-zero (if color monitor).
  1377. ;**                   active page zero.
  1378. ;**                   visual page zero.
  1379. ;**             Width:
  1380. ;**                   80.
  1381. ;**             Color:
  1382. ;**                   foreground  = yellow (14).
  1383. ;**                   background  = blue   (1).
  1384. ;**                   border      = blue   (1).
  1385. ;**             Monochrome:
  1386. ;**                   foreground  = white  (7).
  1387. ;**                   background  = black  (0).
  1388. ;**                   border      = black  (0).
  1389. ;**   USAGE:
  1390. ;**             No parameter required.
  1391. ;**     Returning:
  1392. ;**             VIDEO% - offset to CRT memory.
  1393. ;**             MONO%  - true (-1) if monochrome.
  1394. ;**             ADPT%  - true (-1) if color adapter.
  1395. ;**             FG.%   - foreground: 7=monochrome, 14=color.
  1396. ;**             BG.%   - background: 0=monochrome, 1=color.
  1397. ;**             BD.%   - border: same as background (BG.%).
  1398. ;**   NOTE:
  1399. ;**             &HB000=monochrome offset, &HB800=Color offset.
  1400. ;**             If you call this more than once in a program,
  1401. ;**             you should change it to a procedure subroutine,
  1402. ;**             ie..(_VIDEO).
  1403. ;**
  1404. ;**             **(DEF SEG is set to zero by VIDEO).
  1405. ;**             
  1406. MACRO VIDEO
  1407.    Def Seg=0:VIDEO%=&HB000-(&H800*(((Peek(1040) And 48)/16)<3))|è   MONO%=((Peek(&H410) And &H30)=&H30)|
  1408.    ADPT%=Not MONO%|
  1409.    Screen 0,Abs(ADPT%),0,0|
  1410.    Width 80|
  1411.    FG.%=FG.%+(7*ABS(FG.%=0))|
  1412.    FG.%=(FG.%*(1+ABS(ADPT% And FG.%=7)))|
  1413.    BG.%=BG.%+(1*ABS(BG.%=0))|   
  1414.    BG.%=(BG.%+(MONO%*ABS(BG.%=1)))|
  1415.    BD.%=BG.%|
  1416.    Color FG.%,BG.%,BD.%:Cls
  1417. ENDM
  1418. ;;==========================================================================
  1419. ;**
  1420. ::CRT (Macro)
  1421. ;**   FUNCTION:
  1422. ;**             Screen display.
  1423. ;**   USAGE:
  1424. ;**             Three parameters required.
  1425. ;**             [1] - N/L - screen row.
  1426. ;**             [2] - N/L - screen column.
  1427. ;**             [3] - S/L - display buffer.
  1428. ;**             [4] - L   - optional reverse video.
  1429. ;**   EXAMPLE:
  1430. ;**             $crt 12,25,"HELP"
  1431. ;**             $crt RW.%,CL.%,HELP$,1
  1432. ;**
  1433. MACRO CRT
  1434.    $IF [4]
  1435.    Color BG.%,FG.%
  1436.    $END
  1437.    Locate [1],[2]:Print [3];
  1438.    $IF [5] 
  1439.    Color FG.%,BG.%
  1440.    $END
  1441. ENDM
  1442. ;
  1443.  
  1444.  
  1445. BMLP.P
  1446.  
  1447. '-----------------------------------------------------------------------------
  1448. '- (C) Bendorf Associates, 1984-85                                           -
  1449. '-----------------------------------------------------------------------------
  1450. '- Program:BMLP (BASIC MACRO LANGUAGE PREPROCESSOR)
  1451. '- System :PPE 
  1452. '- Module :TOOLS
  1453. '- Task   :EXPAND MACROS USING LOCAL OR LIBRARY DEFINITIONS.
  1454. '- Created:10.1.82
  1455. '- By     :D. L. BENDORF
  1456. '- Version:PUBLIC DOMAIN
  1457. '- Notes  :THIS PROGRAM IS NOT FOR RESALE.
  1458. '- History:
  1459. '-----------------------------------------------------------------------------
  1460. '- ** Data Division                                                          -
  1461. '-----------------------------------------------------------------------------èSIGN$    = "$"
  1462. DOT$     = "."
  1463. OEXT$    = ".P"         ' Output file default extension
  1464. IEXT$    = ".M"         ' Input file default extension
  1465. LEXT$    = ".ML"        ' Library file default extension
  1466. SOURCE%  = 2            ' Input file number
  1467. O.FILE%  = 1            ' Output file number
  1468. I.FILE%  = 2
  1469. ERRORS%  = 0
  1470. FALSE%   = 0
  1471. TRUE%    = NOT FALSE%
  1472. EXPAND%  = TRUE%
  1473. STORE.%  = 0
  1474. NEST%    = 1
  1475. DIM FILE.%(50)      ' TEMPORARY STACK OF POINTERS TO THE NEXT SUBSCRIPT
  1476.                     ' OF STORE$ ARRAY. ALLOWS NESTED MACROS AND LIBRARIES.
  1477. DIM PARM$(500)      ' TEMPORARY STORAGE OF PARAMETERS TO PASS TO MACROS.
  1478. DIM PARM%(100)      ' ARRAY OF POINTERS TO PARAMETER STORAGE.
  1479.  
  1480. DIM MACRO$(100)     ' STORAGE FOR MACRO NAMES.
  1481. DIM MACRO%(100)     ' ARRAY OF POINTERS TO FIRST CODE LOCATION IN STORE$ ARRAY 
  1482.                     ' FOR EACH MACRO NAME IN THE MACRO$ ARRAY. 
  1483. DIM STORE$(1000)    ' STORAGE FOR MACRO TEXT.
  1484. DIM SUBS$(50)       ' STORAGE FOR MACRO SUBROUTINE NAMES.
  1485. '
  1486. '------------------------------------------------------
  1487. '- ** Procedure Division                              -
  1488. '------------------------------------------------------
  1489. '
  1490. prog BMLP
  1491.     PRINT "BMLP   V1.0B (C) BENDORF ASSOCIATES, 1984-85"
  1492.     PRINT
  1493.     GoSub FILENAMES
  1494.     when I.FILE%>0
  1495.         GoSub PROCESS-SOURCE-FILE
  1496.         CLOSE
  1497.         when ERRORS%>0
  1498.             KILL O.FILE$
  1499.             PRINT O.FILE$;" ABORTED WITH ";STR$(ERRORS%);" ERROR(S)."
  1500.         else
  1501.             PRINT"<";O.FILE$;"> DONE!"
  1502.         endw
  1503.     else when I.FILE$<>""
  1504.         PRINT"CANNOT OPEN ";I.FILE$
  1505.     endw
  1506. pend
  1507. proc PROCESS-SOURCE-FILE
  1508.     OPEN"O",O.FILE%,O.FILE$
  1509.     OPEN"I",I.FILE%,I.FILE$
  1510.     FILE.%(NEST%)=-1
  1511.     loop unless NEST%=0
  1512.         while ENDOFF%=FALSE%
  1513.             GoSub INPUT-BUFFER
  1514.             when LN.%>1 AND ENDOFF%=FALSE%
  1515.                 GoSub INSERT-PARAMETERSè                GoSub PARSE-INPUT-LINE
  1516.             else when SKIP% AND I.FILE%=SOURCE%
  1517.                 PRINT #O.FILE%,BUF$
  1518.             endw
  1519.         wend
  1520.         IF(NEST%=1)THEN FIRST%=0 ELSE FIRST%=PARM%(NEST%-1)
  1521.         LAST%=PARM%(NEST%) 
  1522.         PARM%(NEST%)=0
  1523.         while (FIRST%<LAST%)
  1524.             PARM$(LAST%)=""
  1525.             LAST%=LAST%-1
  1526.         wend
  1527.         when FILE.%(NEST%)<0 AND NEST%>1 AND I.FILE%>SOURCE%
  1528.             CLOSE #I.FILE%
  1529.             I.FILE%=I.FILE%-1
  1530.         else
  1531.             POINTER%=FILE.%(NEST%-1)
  1532.         endw
  1533.         NEST%=NEST%-1
  1534.         ENDOFF%=FALSE%
  1535.         unless NEST%>0 OR SUBS%=LAST.S%
  1536.             LAST.S%=LAST.S%+1
  1537.             TEXT$=SUBS$(LAST.S%)
  1538.             GoSub FIND-MACRO-NAME
  1539.             when FOUND%
  1540.                 FILE.%(NEST%+1)=FIND%:POINTER%=FIND%
  1541.                 NEST%=NEST%+1
  1542.             else
  1543.                 EBUF$="SUBROUTINE ("+TEXT$+") NOT FOUND!"
  1544.                 GoSub ERRORS
  1545.             endw
  1546.         endu
  1547.     endl unless NEST%>0
  1548. endp
  1549. '
  1550. '------------------------------------------------------
  1551. '- ** SubRoutine Division                             -
  1552. '------------------------------------------------------
  1553. '
  1554. proc PARSE-INPUT-LINE
  1555.     GoSub PARSER
  1556.     GoSub LCASE
  1557.     when LEFT$(TEXT$,1)=SIGN$
  1558.         TEXT$=RIGHT$(TEXT$,LEN(TEXT$)-1)
  1559.         when TEXT$="if"
  1560.             GoSub SET-CONDITIONAL
  1561.         else when TEXT$="else" 
  1562.             EXPAND%=(EXPAND%=FALSE%)
  1563.         else when TEXT$="end"
  1564.             EXPAND%=TRUE%
  1565.         else when LEFT$(TEXT$,1)=SIGN$
  1566.             TEXT$=RIGHT$(TEXT$,LEN(TEXT$)-1)
  1567.             GoSub SUBROUTINE
  1568.         else when EXPAND%
  1569.             GoSub EXPAND-MACROè        endw
  1570.     else when TEXT$="macro"
  1571.         GoSub INPUT-A-MACRO
  1572.     else when TEXT$="library"
  1573.         GoSub LIBRARY
  1574.     else when EXPAND% AND I.FILE%=SOURCE%
  1575.         PRINT #O.FILE%,BUF$
  1576.     endw
  1577. endp
  1578. proc INSERT-PARAMETERS
  1579.     LB%=INSTR(1,BUF$,"[")
  1580.     while (LB%>0)
  1581.         RB%=INSTR(LB%,BUF$,"]")
  1582.         when RB%>0
  1583.             INSERT$=PARM$(PARM%(NEST%-1)+VAL(MID$(BUF$,LB%+1,RB%-LB%)))
  1584.             BUF$=LEFT$(BUF$,LB%-1)+INSERT$+RIGHT$(BUF$,LEN(BUF$)-RB%)
  1585.             LB%=INSTR(RB%,BUF$,"[")
  1586.         else
  1587.             LB%=0
  1588.         endw
  1589.     wend
  1590.     LN.%=LEN(BUF$)
  1591. endp
  1592. proc SET-CONDITIONAL
  1593.     GoSub PARSER
  1594.     L$=TEXT$:OP$=""
  1595.     IF(L$="=" OR L$="#" OR L$="<>")THEN OP$=L$:L$=""
  1596.     GoSub PARSER
  1597.     when TEXT$="" 
  1598.         OP$="<>":R$=""
  1599.     else when OP$=""
  1600.         OP$=TEXT$
  1601.         GoSub PARSER
  1602.         R$=TEXT$
  1603.     endw
  1604.     when OP$="="
  1605.         EXPAND%=(R$=L$)
  1606.     else when OP$="<>" OR OP$="#"
  1607.         EXPAND%=(R$<>L$)
  1608.     else
  1609.         EBUF$="ILLEGAL OPERATOR("+OP$+")"
  1610.         GoSub ERRORS
  1611.     endw
  1612. endp
  1613. proc EXPAND-MACRO
  1614.     GoSub FIND-MACRO-NAME
  1615.     when FOUND%
  1616.         IF(FILE.%(NEST%)=>0)THEN FILE.%(NEST%)=POINTER%
  1617.         POINTER%=FIND%
  1618.         NEST%=NEST%+1
  1619.         FILE.%(NEST%)=FIND%
  1620.         PARM%(NEST%)=PARM%(NEST%-1)
  1621.         GoSub LOAD-PARAMETERS
  1622.     else
  1623.         EBUF$="MACRO ("+TEXT$+") NOT DEFINED."è        GoSub ERRORS
  1624.     endw
  1625. endp
  1626. proc LOAD-PARAMETERS
  1627.     PASS%=FALSE%
  1628.     while PASS%=FALSE%
  1629.         PASS%=(CON%=FALSE%)
  1630.         GoSub PARSER
  1631.         while (FIRST%<=LN.%)
  1632.             PARM%(NEST%)=PARM%(NEST%)+1
  1633.             PARM$(PARM%(NEST%))=TEXT$
  1634.             GoSub PARSER
  1635.         wend
  1636.         IF(CON%)THEN GoSub INPUT-SOURCE
  1637.     wend
  1638. endp
  1639. proc INPUT-BUFFER
  1640.     when FILE.%(NEST%)<0
  1641.         GoSub INPUT-SOURCE
  1642.     else
  1643.         BUF$=STORE$(POINTER%)
  1644.         POINTER%=POINTER%+1
  1645.         ENDOFF%=(BUF$=CHR$(7))
  1646.         SKIP%=FALSE%
  1647.         CON%=SKIP%
  1648.         LN.%=LEN(BUF$)
  1649.         INDEX%=0
  1650.     endw
  1651. endp
  1652. proc INPUT-SOURCE
  1653.     INDEX%=0:CON%=FALSE%
  1654.     LINE INPUT #I.FILE%,BUF$
  1655.     ENDOFF%=EOF(I.FILE%)
  1656.     LN.%=LEN(BUF$):I%=1:II%=0
  1657.     while (I%>II% AND I%<LEN(BUF$))
  1658.         II%=I%:I%=I%+ABS(MID$(BUF$,I%,1)=" " OR MID$(BUF$,I%,1)=CHR$(9))
  1659.     wend
  1660.     II%=LN.%+1
  1661.     while (II%>LN.% AND LN.%>I%)
  1662.         II%=LN.%:LN.%=LN.%+(MID$(BUF$,LN.%,1)=" " OR MID$(BUF$,LN.%,1)=CHR$(9))
  1663.     wend
  1664.     BUF$=MID$(BUF$,I%,LN.%):LN.%=LEN(BUF$)
  1665.     SKIP%=(MID$(BUF$,1,1)="'" OR MID$(BUF$,1,1)=";" OR LEN(BUF$)<2)
  1666.     when SKIP%
  1667.         LN.%=1
  1668.     else when RIGHT$(BUF$,2)="\\"
  1669.         CON%=TRUE%
  1670.         BUF$=LEFT$(BUF$,LEN(BUF$)-2)
  1671.         LN.%=LEN(BUF$)
  1672.     endw
  1673. endp
  1674. proc FIND-MACRO-NAME
  1675.     FIND%=FALSE%:THIS.M%=0
  1676.     FOR M%=1 TO LAST.M%
  1677.         IF(MACRO$(M%)=TEXT$)THEN THIS.M%=M%:M%=LAST.M%+1è    NEXT M%
  1678.     FOUND%=(THIS.M%>0)
  1679.     IF(FOUND%)THEN FIND%=MACRO%(THIS.M%)
  1680. endp
  1681. proc INPUT-A-MACRO
  1682.     GoSub PARSER
  1683.     GoSub LCASE
  1684.     GoSub FIND-MACRO-NAME
  1685.     when FOUND%
  1686.         MACRO%(THIS.M%)=STORE.%+1
  1687.     else
  1688.         MACRO$(LAST.M%+1)=TEXT$
  1689.         MACRO%(LAST.M%+1)=STORE.%+1
  1690.         LAST.M%=LAST.M%+1
  1691.     endw
  1692.     GoSub INPUT-SOURCE
  1693.     GoSub PARSER
  1694.     GoSub LCASE
  1695.     while (TEXT$<>"endm" AND ENDOFF%=FALSE%)
  1696.         IF(SKIP%=FALSE%)THEN GoSub STORE-MACRO-CODE
  1697.         GoSub INPUT-SOURCE
  1698.         IF(SKIP%=FALSE%)THEN GoSub PARSER:GoSub LCASE
  1699.     wend
  1700.     BUF$=CHR$(7)
  1701.     GoSub STORE-MACRO-CODE
  1702. endp
  1703. proc STORE-MACRO-CODE
  1704.     STORE.%=STORE.%+1
  1705.     STORE$(STORE.%)=BUF$
  1706. endp
  1707. proc PARSER
  1708.     I%=32
  1709.     while (I%=32)
  1710.         INDEX%=INDEX%+1
  1711.         IF(INDEX%<=LEN(BUF$))THEN I%=ASC(MID$(BUF$,INDEX%,1)) ELSE I%=7
  1712.         I%=I%+(23*ABS(I%=9))
  1713.     wend
  1714.     FIRST%=INDEX%
  1715.     while (I%<>32 AND I%<>7)
  1716.         when I%=44 OR I%=9
  1717.             I%=32 
  1718.         else 
  1719.             when I%=34
  1720.                 X%=INSTR(INDEX%+1,BUF$,CHR$(34))
  1721.                 IF(X%>INDEX%)THEN INDEX%=X%
  1722.             endw
  1723.             INDEX%=INDEX%+1
  1724.             IF(INDEX%<=LEN(BUF$))THEN I%=ASC(MID$(BUF$,INDEX%,1)) ELSE I%=7
  1725.         endw
  1726.     wend
  1727.     TEXT$=MID$(BUF$,FIRST%,INDEX%-FIRST%)
  1728. endp
  1729. proc FILENAMES
  1730.     LINE INPUT"INPUT FILE [.M]:",I.FILE$
  1731.     unless I.FILE$=""è        IF(INSTR(I.FILE$,DOT$)=0)THEN I.FILE$=I.FILE$+IEXT$
  1732.         LK.$=I.FILE$:LK.%=I.FILE%:GoSub _Lookup:I.FILE%=LK.%
  1733.         unless I.FILE%=FALSE%
  1734.             I%=INSTR(1,I.FILE$,DOT$)
  1735.             IF(I%=0)THEN I%=LEN(I.FILE$)+1
  1736.             FILE$=LEFT$(I.FILE$,I%-1)
  1737.             LINE INPUT"OUTPUT FILE [.P]:",O.FILE$
  1738.             IF(O.FILE$="")THEN O.FILE$=FILE$
  1739.             IF(INSTR(O.FILE$,DOT$)=0)THEN O.FILE$=O.FILE$+OEXT$
  1740.         endu
  1741.     endu
  1742. endp
  1743. proc ERRORS
  1744.     ERRORS%=ERRORS%+1
  1745.     EBUF$="ERR#"+STR$(ERRORS%)+" ("+EBUF$+")"
  1746.     PRINT EBUF$
  1747. endp
  1748. proc LCASE
  1749.     I%=1
  1750.     while (I%<=LEN(TEXT$))
  1751.         II%=ASC(MID$(TEXT$,I%,1))
  1752.         MID$(TEXT$,I%,1)=CHR$(II%+(32*ABS(II%>64 AND II%<91))):I%=I%+1
  1753.     wend
  1754. endp
  1755. proc LIBRARY
  1756.     GoSub PARSER
  1757.     unless TEXT$=""
  1758.         IF(INSTR(TEXT$,DOT$)=0)THEN TEXT$=TEXT$+LEXT$
  1759.         LK.%=I.FILE%+1:LK.$=TEXT$:GoSub _Lookup
  1760.         when LK.%>0
  1761.             OPEN"I",LK.%,LK.$:I.FILE%=LK.%
  1762.             NEST%=NEST%+1:FILE.%(NEST%)=-1
  1763.         else
  1764.             EBUF$="LIBRARY ("+LK.$+") NOT FOUND!"
  1765.             GoSub ERRORS
  1766.         endw
  1767.     endu
  1768. endp
  1769. proc _Lookup
  1770.     OPEN"R",LK.%,LK.$:L.K!=LOF(LK.%):CLOSE LK.%
  1771.     IF(L.K!<1)THEN LK.%=0:KILL LK.$
  1772. endp
  1773. proc SUBROUTINE
  1774.     S%=0
  1775.     while (S%<SUBS%)
  1776.         S%=S%+1:IF(TEXT$=SUBS$(S%))THEN S%=SUBS%+1
  1777.     wend
  1778.     IF(S%=SUBS%)THEN SUBS%=SUBS%+1:SUBS$(SUBS%)=TEXT$
  1779. endp
  1780.